﻿using System.Collections.Generic;
using System;
using BCService.Utils;
using BCCommon;
using BCData.TMS.Packing.PackingConfig;
using BCDto.TMS.Packing.PackingConfig;
using BCEntity.TMS.Packing.PackingConfig;
using BCDto.Sim.Admin.Admin;
using BCData.TMS.Packing.PackingCategoryConfig;
using BCEntity.Common.EntityNameConst;
using BCData.TMS.Agent.AgentRecord;
using BCService.Common.Area;
using BCService.TMS.Agent.AgentAreaRecord;
using System.Linq;

namespace BCService.TMS.Packing.PackingConfig
{
    public class PackingConfigService : IPackingConfigService
    {
        private readonly IDatabaseContext databaseContext;
        private readonly IPackingConfigData packingConfigData;
        private readonly IPackingCategoryConfigData packingCategoryConfigData;
        private readonly IPackingConfigOverwriteData packingConfigOverwriteData;
        private readonly IRedisService redisService;
        private readonly IAgentRecordData agentRecordData;
        private readonly IZoneService zoneService;
        private readonly IAgentAreaRecordService agentAreaRecordService;
        private readonly string key = string.Format("{0}", EntityNameConst.PackingConfigEntity);
        private readonly string viewKey = string.Format("{0}", EntityNameConst.PackingConfigViewEntity);

        public PackingConfigService(IDatabaseContext databaseContext,
            IPackingConfigData packingConfigData,
            IPackingCategoryConfigData packingCategoryConfigData,
            IPackingConfigOverwriteData packingConfigOverwriteData,
            IRedisService redisService,
            IAgentRecordData agentRecordData,
            IZoneService zoneService,
            IAgentAreaRecordService agentAreaRecordService)
        {
            this.databaseContext = databaseContext;
            this.packingConfigData = packingConfigData;
            this.packingCategoryConfigData = packingCategoryConfigData;
            this.packingConfigOverwriteData = packingConfigOverwriteData;
            this.redisService = redisService;
            this.agentRecordData = agentRecordData;
            this.zoneService = zoneService;
            this.agentAreaRecordService = agentAreaRecordService;
        }

        /// <summary>
        /// 添加新包装材料配置纪录
        /// </summary>
        /// <param name="requestDto">包装材料配置请求信息</param>
        /// <param name="admin">管理员信息</param>
        /// <returns></returns>
        public PackingConfigDto Add(PackingConfigRequestDto requestDto, AdminDto admin)
        {
            if (admin.CompanyId != 1)
            {
                throw new ArgumentException("您不是总公司员工，暂无权限添加");
            }
            if (requestDto.PackingTitle.Trim().Length > 50)
            {
                throw new ArgumentException("包装材料标题不能多于50字");
            }
            var packingCategoryConfig = this.packingCategoryConfigData.GetEntity(requestDto.PackingCategoryConfigId).Result;
            if (packingCategoryConfig == null)
            {
                throw new ArgumentException("包装材料分类配置信息不存在");
            }
            PackingConfigEntity entity = requestDto.As<PackingConfigEntity>();
            entity.Enabled = true;
            entity.CreateAdminId = admin.AdminId;
            entity.CreateAdminName = admin.FullName;
            entity.CreateTime = DateTime.Now;
            entity.UpdateTime = DateTime.Now;
            entity.EditAdminId = admin.AdminId;
            entity.EditAdminName = admin.FullName;
            var result = this.packingConfigData.InsertAsync(entity).GetAwaiter().GetResult();
            this.redisService.DeleteMultipleKey(key, false);
            return result.As<PackingConfigDto>();
        }

        public void Delete(AdminDto admin, int packingConfigId)
        {
            if (admin.CompanyId != 1)
            {
                throw new ArgumentException("非总公司员工，暂无权限删除");
            }
            //如果是总公司
            var result = this.packingConfigData.GetEntity(packingConfigId).Result;
            if (result == null)
            {
                throw new ArgumentException("包装材料配置信息不存在");
            }
            var packingConfigOverwrite = this.packingConfigOverwriteData.GetEntityByConfigId(packingConfigId).Result;
            if (packingConfigOverwrite != null)
            {
                throw new ArgumentException("此包装材料配置已被代理商重写，无法删除");
            }
            this.packingConfigData.Delete(result.PackingConfigId).GetAwaiter().GetResult();
            string cacheKey = this.redisService.GetKey(key, result.PackingConfigId);
            this.redisService.DeleteMultipleKey(cacheKey, false);
        }

        public IEnumerable<PackingConfigDto> GetList(int? packingCategoryConfigId, string packingTitle, bool? enabled)
        {
            string cacheKey = this.redisService.GetKey(key, packingCategoryConfigId, packingTitle, enabled);
            var result = this.redisService.TryGet(cacheKey, () =>
            {
                var data = this.packingConfigData.GetList(packingCategoryConfigId, packingTitle, enabled).Result;
                return data.As<IEnumerable<PackingConfigDto>>();
            }, TimeSpan.FromDays(30));
            return result.As<IEnumerable<PackingConfigDto>>();
        }

        public PageableList<PackingConfigViewDto> Query(AdminDto admin, int? packingCategoryConfigId, string packingTitle,
            bool? enabled, DateTime? createStartDate, DateTime? createEndDate, int pageIndex, int pageSize)
        {
            //如果是总公司
            string cacheKey = this.redisService.GetKey(key, packingCategoryConfigId, packingTitle, enabled, createStartDate, createEndDate, pageIndex, pageSize);
            var result = this.redisService.TryGet(cacheKey, () =>
            {
                var (data, dataCount) = this.packingConfigData.Query(packingCategoryConfigId, packingTitle, enabled, createStartDate, createEndDate, pageIndex, pageSize).Result;
                return new PageableList<PackingConfigViewDto>()
                {
                    Count = dataCount,
                    Items = data.As<List<PackingConfigViewDto>>(),
                    PageIndex = pageIndex,
                    PageSize = pageSize
                };
            }, TimeSpan.FromDays(30));
            return result;
        }

        #region 获取包装材料配置
        public PackingConfigDto Get(int packingConfigId)
        {
            string cacheKey = this.redisService.GetKey(key, packingConfigId);
            var result = this.redisService.TryGet(cacheKey, () =>
            {
                var data = this.packingConfigData.GetEntity(packingConfigId).GetAwaiter().GetResult();
                return data;
            }, TimeSpan.FromDays(1));
            return result.As<PackingConfigDto>();
        }
        #endregion

        public PackingConfigDto Update(AdminDto admin, int packingConfigId, PackingConfigPutDto putDto)
        {
            if (admin.CompanyId != 1)
            {
                throw new ArgumentException("非总公司员工，暂无权限删除");
            }
            var packingCategoryConfig = this.packingCategoryConfigData.GetEntity(putDto.PackingCategoryConfigId).Result;
            if (packingCategoryConfig == null)
            {
                throw new ArgumentException("包装材料分类配置信息不存在");
            }
            //如果是总公司修改
            var result = this.packingConfigData.GetEntity(packingConfigId).Result;
            if (result == null)
            {
                throw new ArgumentException("包装材料配置信息不存在");
            }
            result.PackingCategoryConfigId = packingCategoryConfig.PackingCategoryConfigId;
            result.PackingTitle = putDto.PackingTitle;
            result.PackingWidth = putDto.PackingWidth;
            result.PackingLength = putDto.PackingLength;
            result.PackingHeight = putDto.PackingHeight;
            result.DimensionUnit = putDto.DimensionUnit.ToString();
            result.ShowUnit = putDto.ShowUnit.ToString();
            result.TransformRatio = putDto.TransformRatio;
            result.Price = putDto.Price;
            result.UpdateTime = DateTime.Now;
            result.EditAdminId = admin.AdminId;
            result.EditAdminName = admin.FullName;
            this.packingConfigData.Update(result).GetAwaiter().GetResult();
            string cacheKey = this.redisService.GetKey(key, result.PackingConfigId);
            this.redisService.DeleteMultipleKey(cacheKey, false);
            return result.As<PackingConfigDto>();
        }

        public IEnumerable<PackingConfigViewDto> GetList(long? agentRecordId, int? packingCategoryConfigId, string provinceCode, string cityCode, string countyCode)
        {
            string cacheKey = this.redisService.GetKey(key, agentRecordId, packingCategoryConfigId, provinceCode, cityCode, countyCode);
            var result = this.redisService.TryGet(cacheKey, () =>
            {
                var configList = this.packingConfigData.GetList(packingCategoryConfigId, null, true).GetAwaiter().GetResult();
                var configOverwriteList = this.packingConfigOverwriteData.GetList(agentRecordId, packingCategoryConfigId, null, true, provinceCode, cityCode, countyCode).Result;
                List<PackingConfigViewEntity> viewList = new List<PackingConfigViewEntity>();
                foreach (var item in configList)
                {
                    if (configOverwriteList.Any(p => p.PackingConfigId == item.PackingConfigId && p.Enabled))
                    {
                        viewList.Add(item);
                    }
                    else if (item.Enabled)
                    {
                        viewList.Add(item);
                    }
                }
                return viewList.As<IEnumerable<PackingConfigViewDto>>();
            }, TimeSpan.FromDays(1));
            return result;
        }

        public PackingConfigDto UpdateEnabled(AdminDto admin, int packingConfigId, bool enabled)
        {
            if (admin.CompanyId != 1)
            {
                throw new ArgumentException("非总公司员工，暂无权限删除");
            }
            var result = this.packingConfigData.GetEntity(packingConfigId).Result;
            if (result == null)
            {
                throw new ArgumentException("包装材料配置信息不存在");
            }
            result.Enabled = enabled;
            result.UpdateTime = DateTime.Now;
            result.EditAdminId = admin.AdminId;
            result.EditAdminName = admin.FullName;
            this.packingConfigData.Update(result).GetAwaiter().GetResult();
            string cacheKey = this.redisService.GetKey(key, result.PackingConfigId);
            this.redisService.DeleteMultipleKey(cacheKey, false);
            return result.As<PackingConfigDto>();
        }
    }
}
